##############################################################################
# table.py
#
# Represents the game table, the environment where everything else exists.
##############################################################################

import bgl, client
import chatbox, whiteboard, helper
# import docbrowser

import sys, pygame
from pygame.locals import *

# A table represents the entire environment within the window. It collects
# input from both the player and the server, manipulating it properly.
class Table(object):
    def __init__(self):
        pygame.init()
        pygame.key.set_repeat(300,25)
        
        pygame.display.set_caption("PyNTT v0.1")
        self.screen = pygame.display.set_mode((800,600), pygame.RESIZABLE)
        
        icon_path = bgl.filename("logo.png")

        try: pygame.display.set_icon(pygame.image.load(icon_path))
        except: pass
        
        self.running = True
        self.clock = pygame.time.Clock()
        
        self.control = client.Client()
        
        self.widgets = []

        self.widgets.append( whiteboard.WhiteBoard( self.control ) )
        # self.widgets.append( docbrowser.DocBrowser( self.control ) )
        self.widgets.append( chatbox.Chatbox( self.control ) )
        self.widgets.append( helper.Helper( self.control ) )
        
        self.bord = 5
        self.bdcolor = (0,155,155)
        self.bgcolor = (0,50,50)
        
        self.focus = None
        self.grab = None
        self.origin = None
        
        self.screen.fill( self.bgcolor )
        pygame.display.update()
        
        self.timer = 0
    
    # Advance the game by one step.
    def run(self):
        case = None
        dirty = False
        very_dirty = False
        
        old_focus = self.focus
        
        # Get all of the player's input up front.
        events = pygame.event.get()
        keys = pygame.key.get_pressed()
        pos = pygame.mouse.get_pos()
        mkeys = pygame.mouse.get_pressed()
        
        new_widgets = []
        kills = []
        
        if self.timer > 0:
            self.timer -= 1
        
        # Update our widgets.
        self.control.update()
        for x in self.widgets:
            w = x.update()
            if not x.running: kills.append(x)
            if w != None and type(w) == list:
                new_widgets += w
        
        for k in kills:
            very_dirty = True
            self.widgets.remove(k)
        
        self.widgets += new_widgets
        if len(new_widgets) > 0:
            self.focus.focus = False
            self.focus = self.widgets[len(self.widgets)-1]
            self.focus.focus = True
        
        # Process the primary event queue.
        for event in events:
            if event.type == QUIT:
                self.running = False
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    if self.timer <= 0:
                        self.control.push("txt","Press Esc again to quit.")
                        self.timer = 100
                    else:
                        self.running = False
            if event.type == MOUSEBUTTONDOWN:
                self.focus = None
                self.grab = None
                counter = range(len(self.widgets)) 
                counter.reverse()
                for x in counter:
                    widget = self.widgets[x]
                    widget.focus = False
                    r = widget.rect
                    if self.focus == None and self.grab == None:
                        if r.collidepoint(pos):
                            self.focus = widget
                            widget.focus = True
                            # widget.on_focus() # Maybe?
                    rx,ry = r.topleft
                    rw,rh = r.size
                    b = self.bord
                    border = pygame.Rect( (rx-b,ry-b,rw+2*b,rh+2*b) )
                    if self.focus == None and border.collidepoint(pos):
                        if self.grab == None:
                            self.grab = widget
                            self.origin = pos
                            dirty = True
                if self.focus != None:
                    if self.focus in self.widgets:
                        self.widgets.remove(self.focus)
                    self.widgets.append(self.focus)
                if self.grab != None:
                    if self.grab in self.widgets:
                        self.widgets.remove(self.grab)
                    self.widgets.append(self.grab)
            if event.type == MOUSEBUTTONUP:
                self.grab = None
                    
        # We then send the event queue to our active widget so we don't have
        # to do a whole bunch of delegation.
        if self.focus != None:
            self.focus.parse_events( events )
        if self.grab != None:
            dx = pos[0] - self.origin[0]
            dy = pos[1] - self.origin[1]
            if dx != 0 or dy != 0:
                very_dirty = True
            self.grab.rect = self.grab.rect.move(dx,dy)
            self.origin = pos
        
        if old_focus is not self.focus:
            dirty = True
        
        # Draw everything.
        if very_dirty:
            self.screen.fill( self.bgcolor )
            dirty = True
        rect_list = []
        for x in self.widgets:
            if x.dirty: dirty = True
            x.dirty = False
            if dirty:
                rx,ry = x.rect.topleft
                rw,rh = x.rect.size
                b = self.bord
                c = self.bdcolor
                pygame.draw.rect(self.screen, c ,(rx-b,ry-b,rw+2*b,rh+2*b))
                pygame.draw.rect(self.screen,(0,0,0), (rx-b,ry-b,rw+2*b,rh+2*b),1)
                pygame.draw.rect(self.screen,(0,0,0), (rx-1,ry-1,rw+2,rh+2),1)
                x.draw( self.screen )
                rect_list.append(pygame.Rect( (rx-b,ry-b,rw+2*b,rh+2*b) ))
        
        if very_dirty: pygame.display.update()
        elif dirty: pygame.display.update(rect_list)
       
    # Loop the game until it ends.
    def play(self):
        while self.running:
            self.clock.tick(60)
            self.run()
        pygame.quit()
